package cn.virens.common.components.bytes;

import cn.virens.common.exception.APIException;

import java.io.Serializable;
import java.nio.ByteBuffer;

@SuppressWarnings("serial")
public class BytesBuffer implements Serializable {
    private final ByteBuffer buffer;

    private int mark = -1;

    protected BytesBuffer(ByteBuffer buffer) {
        this.buffer = buffer;
    }

    /**
     * 打标记点
     *
     * @return 可读长度
     * @throws APIException 一般异常
     */
    public synchronized int mark() throws APIException {
        this.mark = buffer.position();

        return buffer.remaining();
    }

    /**
     * 重置读取下标
     *
     * @param offset 下标偏移量
     * @return 可读长度
     * @throws APIException 一般异常
     */
    public synchronized int reset(int offset) throws APIException {
        if (this.mark >= 0 && buffer.remaining() > offset) {
            this.buffer.position(mark + offset);
        }

        return buffer.remaining();
    }

    /**
     * 获取一个byte
     *
     * @return 数据
     */
    public synchronized byte get() {
        return buffer.get();
    }

    /**
     * 获取一个byte(不影响下标)
     *
     * @param offset 下标偏移量
     * @return 数据
     */
    public synchronized byte get(int offset) {
        return buffer.get(pos(offset));
    }

    /**
     * 获取两个byte
     *
     * @return 数据(short)
     */
    public synchronized short getShort() {
        return buffer.getShort();
    }

    /**
     * 获取两个byte(不影响下标)
     *
     * @param offset 下标偏移量
     * @return 数据(short)
     */
    public synchronized short getShort(int offset) {
        return buffer.getShort(pos(offset));
    }

    /**
     * 获取指定长度的byte数组
     *
     * @param length 数据长度
     * @return 指定数组
     * @throws APIException 一般异常
     */
    public byte[] getBytes(int length) throws APIException {
        if (0 <= length && length <= remaining()) {
            byte[] answer = new byte[length];

            for (int i = 0; i < length; i++) {
                answer[i] = get();
            }

            return answer;
        } else {
            return null;
        }
    }

    /**
     * 获取指定长度的byte数组(不影响下标)
     *
     * @param offset 下标偏移量
     * @param length 数据长度
     * @return 指定数组
     * @throws APIException 一般异常
     */
    public byte[] getBytes(int offset, int length) throws APIException {
        if (0 <= length && length <= remaining()) {
            byte[] answer = new byte[length];

            for (int i = 0; i < length; i++) {
                answer[i] = get(offset + i);
            }

            return answer;
        } else {
            return null;
        }
    }

    /**
     * 获取下标
     *
     * @return 下标
     */
    public synchronized int position() {
        return buffer.position();
    }

    /**
     * 获取可读长度
     *
     * @return 可读长度
     */
    public synchronized int remaining() {
        return buffer.remaining();
    }

    private int pos(int offset) throws APIException {
        return buffer.position() + offset;
    }

    public static BytesBuffer of(ByteBuffer buffer) {
        return new BytesBuffer(buffer);
    }
}
